﻿using System;
using System.Collections.Generic;
using System.Web;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using NFinal.Compile;

namespace NFinal
{
    public class Frame
    {
        private Config config;
        public static string appRoot;
        public static string AssemblyTitle;
        public static string name="NFinal";
        public static bool autoGeneration = false;

        public Frame(Config config,string appRoot)
        {
            this.config = config;
        }
        /// <summary>
        /// 把基于网站根目录的绝对路径改为相对路径
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string MapPath(string url)
        {
            return appRoot + url.Trim('/').Replace('/', '\\');
        }
        /// <summary>
        /// 把路径转为命名空间
        /// </summary>
        /// <param name="folder"></param>
        /// <returns></returns>
        public string GetNameSpace(string folder)
        {
            return NFinal.Frame.AssemblyTitle+"."+folder.Trim('/').Replace('/','.');
        }

        /// <summary>
        /// 从web.config中读取所有的连接字符串信息
        /// </summary>
        public static void CreateDB(string appRoot)
        {
            string configFileName =appRoot + "Web.config";
            if (File.Exists(configFileName))
            {
                System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
                doc.Load(configFileName);
                System.Xml.XmlNode root = doc.DocumentElement.SelectSingleNode("/configuration");
                System.Xml.XmlNodeList nodeList = root.SelectNodes("connectionStrings/add[@connectionString]");
                if (nodeList.Count > 0)
                {
                    System.Xml.XmlElement ele = null;
                    foreach (System.Xml.XmlNode node in nodeList)
                    {
                        ele = node as System.Xml.XmlElement;
                        var connectionString = new NFinal.DB.ConnectionString
                        {
                            name = ele.Attributes["name"].Value,
                            value = ele.Attributes["connectionString"].Value,
                            provider = ele.Attributes["providerName"].Value
                        };
                        if (connectionString.provider.ToLower().IndexOf("mysql") > -1)
                        {
                            connectionString.type = NFinal.DB.DBType.MySql;
                        }
                        else if (connectionString.provider.ToLower().IndexOf("sqlclient") > -1)
                        {
                            connectionString.type = NFinal.DB.DBType.SqlServer;
                        }
                        else if (connectionString.provider.ToLower().IndexOf("sqlite") > -1)
                        {
                            connectionString.type = NFinal.DB.DBType.Sqlite;
                        }
                        else
                        {
                            connectionString.type = NFinal.DB.DBType.Unknown;
                        }
                        Config.ConnectionStrings.Add(connectionString);
                    }
                }
            }

        }
        public static void GetDB(string appRoot)
        {
            Compile.SqlAnalyse analyse=new SqlAnalyse();
            analyse.GetDB(appRoot);
        }
        public void SetDBFile()
        {
            if (Config.ConnectionStrings.Count > 0)
            {
                string dbTplFileName = MapPath("/NFinal/DB/DB.tpl");
                VTemplate.Engine.TemplateDocument doc = null;
                for (int i = 0; i < Config.ConnectionStrings.Count; i++)
                {
                    doc = new VTemplate.Engine.TemplateDocument(dbTplFileName, System.Text.Encoding.UTF8);
                    doc.SetValue("project", Frame.AssemblyTitle);
                    doc.SetValue("app", config.APP.Trim('/'));
                    doc.SetValue("database", Config.ConnectionStrings[i].name);
                    doc.SetValue("name", Config.ConnectionStrings[i].name);
                    doc.SetValue("connectionString", Config.ConnectionStrings[i].value);
                    doc.SetValue("providerName", Config.ConnectionStrings[i].provider);
                    doc.SetValue("dbType",Config.ConnectionStrings[i].type.ToString());
                    doc.RenderTo(MapPath(config.APP + "DB/" + Config.ConnectionStrings[i].name + ".cs"));
                }
                string conStrFileName = MapPath("/NFinal/DB/AppConnectionString.tpl");
                doc = new VTemplate.Engine.TemplateDocument(conStrFileName, System.Text.Encoding.UTF8);
                doc.SetValue("project",Frame.AssemblyTitle);
                doc.SetValue("app",config.APP.Trim('/'));
                doc.SetValue("connectionStrings",Config.ConnectionStrings);
                doc.RenderTo(MapPath(config.APP + "ConnectionString.cs"));
            }
        }
        /// <summary>
        /// 创建目录
        /// </summary>
        /// <param name="folders"></param>
        private void CreateFolders( string[] folders)
        {
            string folder = "/";
            for (int i = 0; i < folders.Length; i++)
            {
                folder = MapPath(folders[i]);
                if (!Directory.Exists(folder))
                {
                    Directory.CreateDirectory(folder);
                }
            }
        }
        //自动创建项目
        public void CreateApp()
        {
            //创建目录
            string[] folders = { config.Controller,
                                   config.Class, 
                                   config.Views,
                                   config.Views+config.defaultStyle,
                                   config.Views+config.defaultStyle+"IndexController/",
                                   config.Model, 
                                   config.Web ,
                                   config.Content,
                                   config.ContentJS,
                                   config.ContentImages,
                                   config.ContentCss,
                                   config.DB
                               };
            CreateFolders(folders);
            //生成首页
            string fileName = MapPath(config.Controller + "IndexController.cs");
            if (!File.Exists(fileName))
            {
                VTemplate.Engine.TemplateDocument doc = new VTemplate.Engine.TemplateDocument(MapPath("/NFinal/Template/IndexController.cs.tpl"),System.Text.Encoding.UTF8);
                doc.SetValue("nameSpace", Frame.AssemblyTitle + "."+config.Controller.Trim('/').Replace('/','.'));
                doc.RenderTo(fileName);
            }
            //生成首页
            fileName = MapPath(config.Views +config.defaultStyle+ "Index"+config.ControllerSuffix+"/" + "Index.aspx");
            if (!File.Exists(fileName))
            {
                File.Copy(MapPath("/NFinal/Template/Index.aspx.tpl"), fileName);
            }
        }
        public static void SetAutoCreateConfig()
        {
            string projectFileName = MapPath("/" + AssemblyTitle + ".csproj");
            bool changed = false;
            
            if (File.Exists(projectFileName))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(projectFileName);
                XmlNamespaceManager xmanager = new XmlNamespaceManager(doc.NameTable);
                string nameSpace = doc.DocumentElement.Attributes["xmlns"].Value;
                xmanager.AddNamespace("x",nameSpace);
                XmlNode nodePostBuildEvent = doc.SelectSingleNode("/x:Project/x:PropertyGroup/x:PreBuildEvent", xmanager);
                if (nodePostBuildEvent == null)
                {
                    changed = true;
                    nodePostBuildEvent = doc.CreateElement("PreBuildEvent", nameSpace);
                    nodePostBuildEvent.InnerText = "$(ProjectDir)NFinal/WebCompiler.exe";
                    XmlNode nodePropertyGroup = doc.CreateElement("PropertyGroup",nameSpace);
                    nodePropertyGroup.AppendChild(nodePostBuildEvent);
                    doc.DocumentElement.AppendChild(nodePropertyGroup);
                }
                else
                {
                    if (nodePostBuildEvent.InnerText == string.Empty)
                    {
                        changed = true;
                        nodePostBuildEvent.InnerText = "$(ProjectDir)NFinal/WebCompiler.exe";
                    }
                }
                if (changed)
                {
                    doc.Save(projectFileName);
                }
            }
        }
        //在某段位置替换成另一段代码
        public int Replace(ref string str,int index,int length,string rep)
        {
            if (length > 0)
            {
                str = str.Remove(index, length);
            }
            if (index > 0)
            {
                str = str.Insert(index, rep);
            }
            return rep.Length - length; 
        }

        //建立编译文件
        public void createCompile()
        {
            //获取所有的controls文件
            string[] fileNames = Directory.GetFiles(MapPath(config.Controller),"*.cs",SearchOption.AllDirectories);

            
            //生成的代码
            string compileCode = "";
            //类名称
            string ClassName = "";

            //前面的字符串部分添加或删除后，后面的代码的相对位置
            int relative_postion=0;

            if(fileNames.Length>0)
            {
                Compiler com = new Compiler();
                FileData fileData = null;
                ClassData classData = null;
                MethodData methodData=null;
                StreamWriter sw = null;
                VTemplate.Engine.TemplateDocument swDebug = null;
                
                string compileFileName = "";
                string compileDir = "";
                string debugFileName="";
                string methodContent="";
                for (int i = 0; i < fileNames.Length; i++)
                {
                    fileData = com.GetFileData(fileNames[i],System.Text.Encoding.UTF8);
                    
                    ClassName = Path.GetFileNameWithoutExtension(fileNames[i]);
                    classData = fileData.GetClassData(ClassName);
                    
                    
                    if (classData.MethodDataList.Count > 0)
                    {
                        
                        for (int j = 0; j < classData.MethodDataList.Count; j++)
                        {
                            //只有公开方法才能访问
                            if (classData.MethodDataList[j].isPublic)
                            {
                                relative_postion = 0;
                                compileCode = fileData.csharpCode.ToString();
                                methodData = classData.MethodDataList[j];
                                //相对
                                compileDir = config.ChangeControllerName(config.Web+config.defaultStyle, (fileData.nameSpace + '.' + ClassName).Replace('.', '/')) + "/";
                                //绝对
                                compileFileName = MapPath(compileDir + methodData.name + ".cs");
                                if (!Directory.Exists(Path.GetDirectoryName(compileFileName)))
                                {
                                    Directory.CreateDirectory(Path.GetDirectoryName(compileFileName));
                                }
                                sw = new StreamWriter(compileFileName,false,System.Text.Encoding.UTF8);
                                relative_postion += Replace(ref compileCode, relative_postion + fileData.start, fileData.length, "namespace " + (Frame.AssemblyTitle + compileDir.TrimEnd('/')).Replace('/', '.') + "\r\n{");
                                relative_postion += Replace(ref compileCode, relative_postion + classData.start, classData.length, "class " +
                                                methodData.name + "Action " + (string.IsNullOrEmpty(classData.baseName) ? "" : " : " + classData.baseName) + "\r\n\t{"
                                                //添加初始化函数
                                                +"\r\n\t\tpublic "+ methodData.name + "Action(System.IO.TextWriter tw):base(tw){}"
                                                +"\r\n\t\tpublic "+ methodData.name + "Action(string fileName) : base(fileName) {}");
                                //循环内部所有方法
                                for (int k = 0; k < classData.MethodDataList.Count; k++)
                                {
                                    //如果两个相等,则进行替换
                                    if (j == k)
                                    {
                                        #region "替换原有方法"
                                        //排除非公开和非基类的方法,替换原有方法体
                                        if (methodData.isPublic)
                                        {
                                            methodContent=methodData.Content;
                                            SqlCompiler sqlCompiler =  new NFinal.Compile.SqlCompiler();
                                            //从代码中分析出数据库相关函数
                                            List<DbFunctionData> dbFunctions = sqlCompiler.Compile(methodContent);
                                            
                                            if (dbFunctions.Count > 0)
                                            {
                                                SqlAnalyse analyse = new SqlAnalyse();
                                                //与数据库相结合,从sql语句中分析出所有的表信息,列信息
                                                methodData.dbFunctions = analyse.FillFunctionDataList(NFinal.DB.Coding.DB.DbStore, dbFunctions);
                                            }
                                             //数据库函数替换
                                            int content_relative_position = 0;
                                            if (dbFunctions.Count > 0)
                                            {
                                                //添加struct类型
                                                for (int s = 0; s < dbFunctions.Count; s++)
                                                {
                                                    string StructData = sqlCompiler.SetMagicStruct(methodData.name, dbFunctions[s], appRoot);
                                                    if (!string.IsNullOrEmpty(StructData))
                                                    {
                                                        compileCode = compileCode.Insert(methodData.start+relative_postion, StructData);
                                                        relative_postion += StructData.Length;
                                                    }
                                                }
                                                content_relative_position += sqlCompiler.SetMagicFunction(methodData.name,
                                                    ref methodContent,
                                                    content_relative_position,
                                                    methodData.dbFunctions,
                                                    appRoot);
                                            }
                                            //从代码中分析出views函数
                                            NFinal.Compile.ViewCompiler viewCompiler = new NFinal.Compile.ViewCompiler();
                                            List<ViewData> views = viewCompiler.Compile(methodContent);
                                            //模版替换
                                            if (views.Count > 0)
                                            {
                                                content_relative_position = 0;
                                                content_relative_position = viewCompiler.SetMagicFunction(ref methodContent,
                                                    content_relative_position,
                                                    fileData.nameSpace,
                                                    ClassName,
                                                    methodData.name, views, config);
                                            }
                                            relative_postion+= Replace(ref compileCode,relative_postion+ methodData.position,methodData.Content.Length, methodContent);
                                            
                                            

                                        }
                                        #endregion
                                    }
                                    //如果两个不相等
                                    else
                                    {
                                        //如果j是公开方法,则进行删除
                                        if (classData.MethodDataList[k].isPublic)
                                        {
                                            compileCode = compileCode.Remove(relative_postion+ classData.MethodDataList[k].start,
                                                classData.MethodDataList[k].length+
                                                classData.MethodDataList[k].Content.Length+1);//去掉最后一个}
                                            relative_postion -= classData.MethodDataList[k].length +
                                                classData.MethodDataList[k].Content.Length + 1;
                                        }
                                        //如果是非公开方法,则保留,即不进行任何其它改变
                                        else
                                        { 
                                        
                                        }
                                    }
                                }
                                sw.Write(compileCode);
                                sw.Close();
                                debugFileName=MapPath(compileDir + methodData.name + ".html");
                                if(!File.Exists(debugFileName))
                                {
                                    swDebug = new VTemplate.Engine.TemplateDocument(MapPath("/NFinal/Template/Debug.tpl"), System.Text.Encoding.UTF8);
                                    swDebug.SetValue("Url",config.ChangeControllerName(config.APP,(fileData.nameSpace + '.' + ClassName).Replace('.', '/'))+"/"+methodData.name+".htm");
                                    swDebug.RenderTo(debugFileName, System.Text.Encoding.UTF8);
                                }
                            }
                        }
                    }
                }
            }
        }
        //创建入口文件
        public void createIndex()
        {
            string page = "Default";
            VTemplate.Engine.TemplateDocument doc_aspx = new VTemplate.Engine.TemplateDocument(MapPath("/NFinal/Index/Index.aspx.cs.tpl"),
                System.Text.Encoding.UTF8);
            doc_aspx.SetValue("assm", NFinal.Frame.AssemblyTitle);
            doc_aspx.SetValue("page",page);
            doc_aspx.SetValue("app",config.APP.Trim('/'));
            doc_aspx.RenderTo(MapPath(page+".aspx.cs"));

            doc_aspx = new VTemplate.Engine.TemplateDocument(MapPath("/NFinal/Index/Index.aspx.designer.cs.tpl"),
                System.Text.Encoding.UTF8);
            doc_aspx.SetValue("assm", NFinal.Frame.AssemblyTitle);
            doc_aspx.SetValue("page", page);
            doc_aspx.SetValue("app", config.APP.Trim('/'));
            doc_aspx.RenderTo(MapPath(page+ ".aspx.designer.cs"));

            doc_aspx = new VTemplate.Engine.TemplateDocument(MapPath("/NFinal/Index/Index.aspx.tpl"),
                System.Text.Encoding.UTF8);
            doc_aspx.SetValue("assm", NFinal.Frame.AssemblyTitle);
            doc_aspx.SetValue("page", page);
            doc_aspx.SetValue("app", config.APP.Trim('/'));
            doc_aspx.RenderTo(MapPath(page + ".aspx"));
        }
        //创建分组路由器
        public void CreateRouter()
        {
            string[] fileNames = Directory.GetFiles(MapPath(config.Controller),"*.cs",SearchOption.AllDirectories);
           
            string ClassName = null;
            Compiler compiler=new Compiler();
            FileData fileData=null;
            ClassData classData=null;

            List<ClassData> classDataList = new List<ClassData>();
            string temp=null;
            if (fileNames.Length > 0)
            {
                for (int i = 0; i < fileNames.Length; i++)
                {

                    fileData = compiler.GetFileData(fileNames[i],System.Text.Encoding.UTF8);
                    ClassName = Path.GetFileNameWithoutExtension(fileNames[i]);
                    classData = fileData.GetClassData(ClassName);
                    temp = (Frame.AssemblyTitle + config.Controller).TrimEnd('/');
                    //relativeName="/Manage/IndexController"
                    //RelativeDotName=".Manage.IndexController"
                    classData.relativeName =classData.fullName.Substring(temp.Length,classData.fullName.Length-temp.Length).Replace('.','/');
                    classData.relativeDotName = classData.fullName.Substring(temp.Length, classData.fullName.Length - temp.Length);
                    classDataList.Add(classData);
                }
            }
            
            VTemplate.Engine.TemplateDocument doc = new VTemplate.Engine.TemplateDocument(MapPath("NFinal/Template/Router.tpl"), System.Text.Encoding.UTF8);
            doc.SetValue("defaultStyle",config.defaultStyle.Trim('/'));
            doc.SetValue("classDataList", classDataList);
            doc.SetValue("namespace", config.GetFullName(fileData.projectName,config.APP));
            doc.SetValue("app",config.APP);
            doc.RenderTo(MapPath(config.APP+"Router.cs"), System.Text.Encoding.UTF8);
        }
        public static void CreateMain(string[] apps)
        {
            //创建主路由
            VTemplate.Engine.TemplateDocument doc = null;
            doc=new VTemplate.Engine.TemplateDocument(MapPath("NFinal/Template/Main.tpl"), System.Text.Encoding.UTF8);
            doc.SetValue("project", NFinal.Frame.AssemblyTitle);
            doc.SetValue("apps", apps);
            doc.SetValue("ControllerSuffix", "Controller");
            doc.RenderTo(MapPath("NFinal/Main.cs"), System.Text.Encoding.UTF8);
        }
        public static XmlNode CreateXMLPath(XmlDocument doc, string root)
        {
            string[] pathes = root.Trim('/').Split('/');
            string oldXpath = "", newXpath = "";
            if (pathes.Length > 1)
            {
                newXpath = pathes[0];
                XmlNode newNode = null, oldNode = null;
                for (int i = 1; i < pathes.Length; i++)
                {
                    oldXpath = newXpath;
                    newXpath += "/" + pathes[i];
                    newNode = doc.SelectSingleNode(newXpath);

                    oldNode = doc.SelectSingleNode(oldXpath);
                    if (newNode == null)
                    {
                        newNode = doc.CreateElement(pathes[i]);
                        oldNode.AppendChild(newNode);
                    }
                }
                return newNode;
            }
            return doc.DocumentElement;
        }
        //自动配置WebConfig
        public static string[] GetWebConfig(bool isNewIIS,string appRoot)
        {
            Frame.appRoot = appRoot;
            Frame.AssemblyTitle = new DirectoryInfo(Frame.appRoot).Name;
            //文档是否变动
            bool changed = false;
            //配置.net信息
            string webConfig = MapPath("/Web.config");
            if (!File.Exists(webConfig))
            {
                changed = true;
                File.Copy(MapPath("/NFinal/Template/Web.config.tpl"), MapPath("/Web.config"));
                File.Copy(MapPath("/NFinal/Template/Web.config.Debug.tpl"), MapPath("/Web.Debug.config"));
                File.Copy(MapPath("/NFinal/Template/Web.config.Release.tpl"), MapPath("/Web.Release.config"));
            }
            //根据环境配置webconfig
            System.Xml.XmlDocument doc = new XmlDocument();
            doc.Load(webConfig);
            XmlNode root = doc.DocumentElement;
            if (root == null)
            {
                return null;
            }
            //读取Apps中的值
            XmlNode appsNode = doc.DocumentElement.SelectSingleNode("appSettings/add[@key='Apps']");
            string[] Apps = null;

            if (appsNode != null && appsNode.Attributes.Count > 0 && appsNode.Attributes["value"] != null)
            {
                Apps = appsNode.Attributes["value"].Value.Split(',');
            }
            else
            {
                changed = true;
                XmlNode appSettingNode = CreateXMLPath(doc, "configuration/appSettings");
                appsNode = doc.CreateElement("add");
                XmlAttribute attrKey = doc.CreateAttribute("key");
                attrKey.Value = "Apps";
                XmlAttribute attrValue = doc.CreateAttribute("value");
                attrValue.Value = "App";
                appsNode.Attributes.RemoveAll();
                appsNode.Attributes.Append(attrKey);
                appsNode.Attributes.Append(attrValue);
                appSettingNode.AppendChild(appsNode);
                Apps = new string[] { "App" };
            }
            //读取是否自动生成
            XmlNode autoGenerationNode = doc.DocumentElement.SelectSingleNode("appSettings/add[@key='AutoGeneration']");
            bool autoGeneration = false;
            if (autoGenerationNode != null)
            {
                autoGeneration = autoGenerationNode.Attributes["value"].Value.ToLower() == "true";
            }
            else
            {
                changed = true;
                XmlNode appSettingNode = CreateXMLPath(doc, "configuration/appSettings");
                appsNode = doc.CreateElement("add");
                XmlAttribute attrKey = doc.CreateAttribute("key");
                attrKey.Value = "AutoGeneration";
                XmlAttribute attrValue = doc.CreateAttribute("value");
                attrValue.Value = "false";
                appsNode.Attributes.RemoveAll();
                appsNode.Attributes.Append(attrKey);
                appsNode.Attributes.Append(attrValue);
                appSettingNode.AppendChild(appsNode);
                autoGeneration = false;
            }
            Frame.autoGeneration = autoGeneration;
            //创建URL重写的主页文件
            if (!File.Exists(MapPath("/Index.html")))
            {
                VTemplate.Engine.TemplateDocument docIndex=new VTemplate.Engine.TemplateDocument(MapPath("/NFinal/Template/Index.html"),System.Text.Encoding.UTF8);
                docIndex.SetValue("App", Apps[0]);
                docIndex.RenderTo(MapPath("/Index.html"));
            }
            //删除UrlRewriter
            string urlRewriterFileName = MapPath("/bin/URLRewriter.dll");
            if (File.Exists(urlRewriterFileName))
            {
                File.Delete(urlRewriterFileName);
            }
            //添加UrlRewriter
            XmlNode nodeConfigSection = doc.DocumentElement.SelectSingleNode("configSections/section[@name='RewriterConfig']");
            if (nodeConfigSection == null)
            {
                changed = true;

                XmlNode nodeSection = doc.CreateElement("section");
                XmlAttribute attrName = doc.CreateAttribute("name");
                attrName.Value = "RewriterConfig";
                XmlAttribute attrType = doc.CreateAttribute("type");
                attrType.Value = "NFinal.URLRewriter.Config.RewriterConfigSerializerSectionHandler";
                nodeSection.Attributes.Append(attrName);
                nodeSection.Attributes.Append(attrType);

                XmlNode nodeConfigSections = doc.DocumentElement.SelectSingleNode("configSections");

                if (nodeConfigSections == null)
                {
                    nodeConfigSections = doc.CreateElement("configSections");
                    doc.DocumentElement.InsertBefore(nodeConfigSections, doc.DocumentElement.FirstChild); 
                }
                nodeConfigSections.AppendChild(nodeSection);
            }

            XmlNode nodeRewriteSection = doc.DocumentElement.SelectSingleNode("configSections/section[@name='RewriterConfig']");
            //修正属性
            if (nodeRewriteSection.Attributes["type"].Value.IndexOf(",") > -1)
            {
                changed = true;
                nodeRewriteSection.Attributes["type"].Value = "NFinal.URLRewriter.Config.RewriterConfigSerializerSectionHandler";
            }
  
            XmlNode nodeRewriterConfig = doc.DocumentElement.SelectSingleNode("RewriterConfig");
            if (nodeRewriterConfig == null)
            {
                changed = true;
                XmlNode nodeRules=CreateXMLPath(doc,"configuration/RewriterConfig/Rules");
                XmlNode nodeRewriterRule=doc.CreateElement("RewriterRule");
                XmlNode nodeLookFor=doc.CreateElement("LookFor");
                nodeLookFor.InnerText="~/Index.html";
                XmlNode nodeSendTo=doc.CreateElement("SendTo");
                nodeSendTo.InnerText=string.Format("~/{0}/IndexController/Index.htm",Apps[0]);
                nodeRewriterRule.AppendChild(nodeLookFor);
                nodeRewriterRule.AppendChild(nodeSendTo);
                nodeRules.AppendChild(nodeRewriterRule);
            }
            //如果是IIS7以上版本
            if (isNewIIS)
            {
                //如果是旧版本,则注释掉旧版本的节点
                XmlNode oldConfigSection = doc.DocumentElement.SelectSingleNode("system.web");
                if (oldConfigSection != null)
                {
                    changed = true;
                    root.RemoveChild(oldConfigSection);
                }
                //添加NFinal节点属性
                XmlNode newFactoryNode = doc.DocumentElement.SelectSingleNode("system.webServer/handlers/add[@type='NFinal.Handler.HandlerFactory']");
                //不存在则添加
                if (newFactoryNode == null)
                {
                    changed = true;
                    XmlNode handlersNode = CreateXMLPath(doc, "configuration/system.webServer/handlers");
                    XmlNode NFinalHandlerNode = doc.CreateElement("add");
                    XmlAttribute attrName = doc.CreateAttribute("name");
                    attrName.Value = "NFinalHandlerFactory";
                    XmlAttribute attrVerb = doc.CreateAttribute("verb");
                    attrVerb.Value = "*";
                    XmlAttribute attrPath = doc.CreateAttribute("path");
                    attrPath.Value = "*.htm";
                    XmlAttribute attrType = doc.CreateAttribute("type");
                    attrType.Value = "NFinal.Handler.HandlerFactory";
                    XmlAttribute attrPreCondition = doc.CreateAttribute("preCondition");
                    attrPreCondition.Value = "integratedMode";
                    NFinalHandlerNode.Attributes.RemoveAll();
                    NFinalHandlerNode.Attributes.Append(attrName);
                    NFinalHandlerNode.Attributes.Append(attrVerb);
                    NFinalHandlerNode.Attributes.Append(attrPath);
                    NFinalHandlerNode.Attributes.Append(attrType);
                    NFinalHandlerNode.Attributes.Append(attrPreCondition);
                    handlersNode.AppendChild(NFinalHandlerNode);
                }
                //添加Rewriter节点属性
                XmlNode newRewriterNode = doc.DocumentElement.SelectSingleNode("system.webServer/modules/add[@name='ModuleRewriter']");
                if (newRewriterNode == null)
                {
                    changed = true;
                    XmlNode modulesNode = CreateXMLPath(doc, "configuration/system.webServer/modules");
                    XmlNode urlRewriterNode = doc.CreateElement("add");
                    XmlAttribute attrName = doc.CreateAttribute("name");
                    attrName.Value = "ModuleRewriter";
                    XmlAttribute attrType = doc.CreateAttribute("type");
                    attrType.Value = "NFinal.URLRewriter.ModuleRewriter";
                    urlRewriterNode.Attributes.Append(attrName);
                    urlRewriterNode.Attributes.Append(attrType);
                    modulesNode.AppendChild(urlRewriterNode);
                }
                XmlNode nodeModules = doc.DocumentElement.SelectSingleNode("system.webServer/modules/add[@name='ModuleRewriter']");
                if (nodeModules.Attributes["type"] != null)
                {
                    if (nodeModules.Attributes["type"].Value.IndexOf(",") > -1)
                    {
                        changed = true;
                        nodeModules.Attributes["type"].Value = "NFinal.URLRewriter.ModuleRewriter";
                    }
                }
            }
            //如果是IIS7以下版本
            else
            {
                XmlNode newConfigSection = doc.DocumentElement.SelectSingleNode("system.webServer");

                if (newConfigSection != null)
                {
                    changed = true;
                    root.RemoveChild(newConfigSection);
                }
                //添加NFinal节点属性
                XmlNode newFactoryNode = doc.DocumentElement.SelectSingleNode("system.web/httpHandlers/add[@type='NFinal.Handler.HandlerFactory']");
                //不存在则添加
                if (newFactoryNode == null)
                {
                    changed = true;
                    XmlNode handlersNode = CreateXMLPath(doc, "configuration/system.web/httpHandlers");
                    XmlNode NFinalHandlerNode = doc.CreateElement("add");
                    XmlAttribute attrVerb = doc.CreateAttribute("verb");
                    attrVerb.Value = "*";
                    XmlAttribute attrPath = doc.CreateAttribute("path");
                    attrPath.Value = "*.htm";
                    XmlAttribute attrType = doc.CreateAttribute("type");
                    attrType.Value = "NFinal.Handler.HandlerFactory";
                    NFinalHandlerNode.Attributes.RemoveAll();
                    NFinalHandlerNode.Attributes.Append(attrVerb);
                    NFinalHandlerNode.Attributes.Append(attrPath);
                    NFinalHandlerNode.Attributes.Append(attrType);
                    handlersNode.AppendChild(NFinalHandlerNode);
                }
                
                //添加Rewriter节点属性
                XmlNode newRewriterNode = doc.DocumentElement.SelectSingleNode("system.web/httpModules/add[@type='NFinal.URLRewriter.ModuleRewriter']");
                if (newRewriterNode == null)
                {
                    changed = true;
                    XmlNode modulesNode = CreateXMLPath(doc, "configuration/system.web/httpModules");
                    XmlNode urlRewriterNode = doc.CreateElement("add");
                    XmlAttribute attrName = doc.CreateAttribute("name");
                    attrName.Value = "ModuleRewriter";
                    XmlAttribute attrType = doc.CreateAttribute("type");
                    attrType.Value = "NFinal.URLRewriter.ModuleRewriter";
                    urlRewriterNode.Attributes.Append(attrName);
                    urlRewriterNode.Attributes.Append(attrType);
                    modulesNode.AppendChild(urlRewriterNode);
                }
                XmlNode nodeModules = doc.DocumentElement.SelectSingleNode("system.web/httpModules/add[@name='ModuleRewriter']");
                if (nodeModules.Attributes["type"] != null)
                {
                    if (nodeModules.Attributes["type"].Value.IndexOf(",") > -1)
                    {
                        changed = true;
                        nodeModules.Attributes["type"].Value = "NFinal.URLRewriter.ModuleRewriter";
                    }
                }
            }
            //如果文档变动就保存
            if (changed)
            {
                doc.Save(webConfig);
            }
            return Apps;
        }
    }

}